package com.dbsync.core;

import org.slf4j.Logger;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.List;
import java.util.Map;

/**
 * SQL执行线程类
 */
public class DataInsertThead extends Thread {
    // 日志
    private Logger logger;
    // 线程索引
    private int theadIndex;
    // 任务索引
    private int targetIndex;
    // 数据库工具对象
    private DBUtil dbUtil;
    // 数据list集合
    private List<Map<String, Object>> dataList;
    // 表名
    private StringBuilder tableName = new StringBuilder();

    public DataInsertThead(int theadIndex, int targetIndex, DBUtil dbUtil, List<Map<String, Object>> dataList, String tableName, Logger logger) {
        this.theadIndex = theadIndex;
        this.targetIndex = targetIndex;
        this.dbUtil = dbUtil;
        this.dataList = dataList;
        this.tableName.append(tableName);
        this.logger = logger;
    }

    @Override
    public void run(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = this.dbUtil.getMoreTargetConnection(this.targetIndex);
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement(this.getSQL(this.dataList.get(0)));
            if ("mysql".equalsIgnoreCase(this.dbUtil.getDBType(this.targetIndex))){
                preparedStatement.addBatch("SET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\"");
            }
            double count = this.dataList.size();
            int percent = 1;
            for (int i=1;i<=count;i++){
                Map<String, Object> data = this.dataList.get(i-1);
                int pindex = 1;
                for (Map.Entry<String, Object> entry : data.entrySet()){
                    preparedStatement.setObject(pindex, entry.getValue());
                    pindex++;
                }
                preparedStatement.addBatch();
                data.clear();
                if(i%1000==0||i==count){
                    preparedStatement.executeBatch();
                    connection.commit();
                    preparedStatement.clearParameters();
                }
                if (i/count*100>=percent){
                    logger.info("[数据同步线程"+this.theadIndex+"]已完成"+(Double.valueOf(i/count*100).intValue())+"%，请稍后......");
                    percent++;
                }
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            try {
                if (preparedStatement != null){
                    preparedStatement.clearParameters();
                    preparedStatement.close();
                }
                if (connection != null){
                    connection.close();
                }
            }catch (Exception e1){
                throw new RuntimeException(e1);
            }
        }
    }

    /**
     * 获取组装好的sql语句
     * @param data 参数集合
     * @return 返回sql语句
     */
    private String getSQL(Map<String, Object> data){
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO ").append(tableName).append("(#columnNames#)").append(" VALUE(#columnValues#)");
        StringBuilder columnNames = new StringBuilder();
        StringBuilder columnValues = new StringBuilder();
        for (Map.Entry<String, Object> entry : data.entrySet()){
            columnNames.append(entry.getKey()).append(",");
            columnValues.append("?,");
        }
        return sql.toString()
                .replace("#columnNames#", columnNames.substring(0, columnNames.length()-1))
                .replace("#columnValues#", columnValues.substring(0, columnValues.length()-1));
    }
}
